package com.qcxy.gzy.activity;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.qcxy.gzy.activity.base.BaseSwitchActivity;
import com.qcxy.gzy.activity.v4.SwitchEMActivity;
import com.qcxy.gzy.bean.ComReceiveDataBean;
import com.qcxy.gzy.bean.SerialPortCommand;
import com.qxcy.gzy.util.PreferencesUtils;
import com.qxcy.gzy.util.SerialPortUtils;

import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class ExerciseActivity extends SwitchEMActivity implements SwitchEMActivity.SwitchEMListener, BaseSwitchActivity.BreakdownListener {
    private int mShowWeight = 10;//当前力量
    private static final int limitWeight = 30;//切换大电机临界值
    private static final int limitWeightSmall = 20;//切换小电机临界值
    private int gear = 0;//1或者10或者0
    private static final int WeightMax = 150, WeightMin = 5;
    private int switchNum = 0;//切换次数
    private boolean isNeedBig;//是否切换为大电机

    private Timer exerciseTimer;//计时器
    private TimerTask exerciseTask;
    private int exerciseCount;//计时秒数
    private int weightSetCount;//力量操作间隔
    private int oldWeight;//记录历史力量

    private StringBuilder exerciseBuilder;
    private static final String TAG = "ExerciseActivity";
    private boolean isExercise = true;//是否锻炼中
    /**
     * 当前动作状态
     * -1:当前无命令执行
     * 0：力量发送中
     * 1：距离读取中
     * 2：电机切换中
     */
    private int actionStatus = -1;
    /**
     * 0:读
     * 1：设置力量
     * 2：切换大电机
     * 3：切换小电机
     */
    private int otherAfterAction = 0;//当（读距离或者设置力量）命令结束后，检查是否存在等待命令

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_v4_exercise);
        ButterKnife.bind(this);
        exerciseBuilder = new StringBuilder();
        status = 5;
        isExercise = true;
        mShowWeight = runEMType == SerialPortUtils.ElectricMachineryBig ? 30 : 10;
        oldWeight = mShowWeight;
        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
        actionStatus = -1;
        weightSetCount = 0;
        exerciseCount = 0;
        otherAfterAction = 0;
        //发送设置力量
        setPower();
        //开启计时
        startTimer();
    }


    public void setPower() {
        if (isEMSwitching) return;
        if (actionStatus == -1) {
            exerciseBuilder.append(TAG).append("发送设置力量命令").append("\n");
            builderWExercise(TAG);
            wExercise("发送设置力量命令");
            actionStatus = 0;
            runEMType = (int) PreferencesUtils.get(this, SerialPortUtils.CURRENT_EM, SerialPortUtils.ElectricMachinerySmall);
            byte[] commandPower = SerialPortUtils.getPowerCommand(runEMType, mShowWeight);
            currentCommand = new SerialPortCommand(commandPower, SerialPortCommand.COM_TYPE_SET_POWER);
            sendCommand(currentCommand);
        } else {
            if (otherAfterAction == 0) {
                exerciseBuilder.append(TAG).append("当前存在执行命令，等命令执行完毕，再启动设置力量").append("\n");
                builderWExercise(TAG);
                wExercise("当前存在执行命令，等命令执行完毕，再启动设置力量");
                otherAfterAction = 1;
            }
        }
    }

    public void readDistance() {
        if (!isExercise) return;
        if (isEMSwitching) return;
        wExercise("actionStatus:" + actionStatus);
        //空闲时间读运动距离
        if (actionStatus == -1) {
            exerciseBuilder.append(TAG).append("发送读运动距离命令").append("\n");
            builderWExercise(TAG);
            wExercise("发送读运动距离命令");
            actionStatus = 1;
            runEMType = (int) PreferencesUtils.get(this, SerialPortUtils.CURRENT_EM, SerialPortUtils.ElectricMachinerySmall);
            byte[] commandDistance = SerialPortUtils.getEDCommand(runEMType);
            currentCommand = new SerialPortCommand(commandDistance, SerialPortCommand.COM_TYPE_READ_DISTANCE);
            sendCommand(currentCommand);
        }
    }

    private void autoSwitch(final boolean isBig) {
        if (isEMSwitching) return;
        if (actionStatus != -1) {
            if (otherAfterAction == 0 || otherAfterAction == 1) {
                exerciseBuilder.append(TAG).append("当前存在执行命令，等命令执行完毕，再启动切换流程").append("\n");
                builderWExercise(TAG);
                wExercise("当前存在执行命令，等命令执行完毕，再启动切换流程");
                showDialog(loading);
                otherAfterAction = isBig ? 2 : 3;
            }
        } else {
            exerciseBuilder.append(TAG).append("启动命令切换").append("\n");
            builderWExercise(TAG);
            wExercise("启动命令切换");
            actionStatus = 2;
            isEMSwitching = true;
            isNeedBig = isBig;
            boolean isCurrentBig = runEMType == SerialPortUtils.ElectricMachineryBig;
            if (isCurrentBig == isBig) {
                actionStatus = -1;
                isEMSwitching = false;
                return;
            }
            switchEM(isBig);
        }
    }

    private void switchEM(final boolean isBig) {
        if (isBig) {
            //切换至大电机
            switchToEMBig();
        } else {
            //切换至小电机
            switchToEMSmall();
        }
    }

    @Override
    public void onSwitch(final boolean isSuccess, final String message, final int type) {
        hideLoadingView();
        actionStatus = -1;
        switchNum++;
        builder.delete(0, builder.length());
        //日志相关
        builder.append(TAG).append("切换结果：").append(isSuccess ? "成功" : "失败").append("\n");
        if (!isSuccess) {
            builder.append(TAG).append("切换失败信息").append(message).append("\n");
        }
        builder.append(TAG).append("------------------------------------------------------------------------\n");
        SerialPortUtils.saveLocalDailyLog(builder.toString());
        builderWExercise(TAG);
        exerciseBuilder.append("电机切换结果：").append(isSuccess ? "成功" : "失败").append("\n");
        builderWExercise(TAG);
        wExercise("电机切换结果：" + (isSuccess ? "成功" : "失败"));
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isSuccess) {
                    isEMSwitching = false;
                    switchNum = 0;
                    //暂存电机信息
                    PreferencesUtils.put(ExerciseActivity.this, SerialPortUtils.CURRENT_EM, type);
                    toast("电机切换成功");
                    if (gear != 0) {
                        if (type == SerialPortUtils.ElectricMachineryBig) {
                            mShowWeight = mShowWeight + gear;
                        } else {
                            mShowWeight = mShowWeight - gear;
                        }
                        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
                        weightSetCount = 0;
                        oldWeight = mShowWeight;
                        //发送设置力量
                        setPower();
                    }
                } else {
                    if (switchNum < 3) {
                        isEMSwitching = true;
                        actionStatus = 2;
                        switchEM(isNeedBig);
                    } else {
                        isEMSwitching = false;
                        switchNum = 0;
                        SerialPortUtils.showSerialDialog(ExerciseActivity.this, "提示", message);
                    }
                }
            }
        });
    }

    @Override
    public void onBackPressed() {
        finish();
    }

    @OnClick({R.id.iv_back, R.id.zl_zj_10, R.id.zl_zj_1, R.id.zl_js_1, R.id.zl_js_10, R.id.show_pause, R.id.show_restart})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_back:
                onBackPressed();
                break;
            case R.id.zl_zj_1:
                gear = 1;
                if (isEMSwitching) return;
                if (mShowWeight < limitWeight && (mShowWeight + 1) >= limitWeight && runEMType == SerialPortUtils.ElectricMachinerySmall) {
                    autoSwitch(true);
                } else {
                    if (mShowWeight <= WeightMax) {
                        mShowWeight++;
                        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
                        weightSetCount = 0;
                    } else {
                        toast(R.string.max_weight);
                    }
                }
                break;
            case R.id.zl_js_1:
                gear = 1;
                if (isEMSwitching) return;
                if (mShowWeight >= limitWeightSmall && (mShowWeight - 1) < limitWeightSmall && runEMType == SerialPortUtils.ElectricMachineryBig) {
                    autoSwitch(false);
                } else {
                    if (mShowWeight > WeightMin) {
                        mShowWeight--;
                        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
                        weightSetCount = 0;
                    } else {
                        toast(R.string.min_weight);
                    }
                }
                break;
            case R.id.zl_zj_10:
                gear = 10;
                if (isEMSwitching) return;
                if (mShowWeight < limitWeight && (mShowWeight + 10) >= limitWeight && runEMType == SerialPortUtils.ElectricMachinerySmall) {
                    autoSwitch(true);
                } else {
                    if (mShowWeight <= WeightMax) {
                        if (mShowWeight + gear >= WeightMax) {
                            mShowWeight = WeightMax;
                        } else {
                            mShowWeight = mShowWeight + gear;
                        }
                        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
                        weightSetCount = 0;
                    } else {
                        toast(R.string.max_weight);
                    }
                }
                break;
            case R.id.zl_js_10:
                gear = 10;
                if (isEMSwitching) return;
                if (mShowWeight >= limitWeightSmall && (mShowWeight - 10) < limitWeightSmall && runEMType == SerialPortUtils.ElectricMachineryBig) {
                    autoSwitch(false);
                } else {
                    if (mShowWeight > WeightMin) {
                        if (mShowWeight > gear) {
                            mShowWeight = mShowWeight - gear;
                        } else {
                            mShowWeight = 1;
                        }
                        tvTargetShowWeight.setText(String.valueOf(mShowWeight));
                        weightSetCount = 0;
                    } else {
                        toast(R.string.min_weight);
                    }
                }
                break;
            case R.id.show_pause:
                //读与计时
                isExercise = !isExercise;
                if (isExercise) {
                    //发送设置力量，来启动循环
                    setPower();
                }
                playOrStop.setBackgroundResource(isExercise ? R.drawable.icon_ztxl : R.drawable.icon_zxxl);
                playStopTxt.setText(isExercise ? "暂停训练" : "继续训练");
                break;
            case R.id.show_restart:
                if (isExercise) {
                    exerciseCount = 0;
                    mRealCounts = 0;
                    calorie = 0;
                } else {
                    isExercise = true;
                    //发送设置力量，来启动循环
                    setPower();
                }
                playOrStop.setBackgroundResource(R.drawable.icon_ztxl);
                playStopTxt.setText("暂停训练");
                break;
        }
    }

    @Override
    protected void onDataReceived(final ComReceiveDataBean ComRecData) {
        if (!isAlive) {
            isCommandRun = false;
            if (resendThread != null) {
                resendThread.stopSend();
                resendThread = null;
            }
            return;
        }
        wBase("isEMSwitching:" + isEMSwitching);
        if (actionStatus != 2 && !isEMSwitching) {
            exerciseBuilder.append(TAG).append("收到返回值1：").append(new Gson().toJson(ComRecData.bRec)).append("\n");
            builderWExercise(TAG);
            wExercise("收到:" + json(ComRecData.bRec));
            if (verification(ComRecData)) {
                isCommandRun = false;
                if (resendThread != null) {
                    resendThread.stopSend();
                    resendThread = null;
                }
                switch (currentCommand.command[1]) {
                    case SerialPortUtils.typeRead://读
                        if (ComRecData.bRec[1] == SerialPortUtils.typeRead) {
                            byte address = currentCommand.command[3];
                            if (address == SerialPortUtils.addressDistance && actionStatus == 1) {//读距离
                                exerciseBuilder.append(TAG).append("读运动距离成功").append("\n");
                                builderWExercise(TAG);
                                byte[] dBytes = new byte[]{0x00, 0x00, ComRecData.bRec[3], ComRecData.bRec[4]};
                                int distance = SerialPortUtils.byteArrayToInt(dBytes);
                                if (distance >= 1500) { // 检测到距离大于60%最大距离时
                                    mStatus = 1; // 拉伸状态变为1
                                    if (distance4Calorie < distance) {
                                        distance4Calorie = distance;
                                    }
                                }
                                // 拉伸状为1并且 检测到距离小于30%最大距离时拉伸状态变为
                                if (mStatus == 1 && distance < 1500) {
                                    mRealCounts++; // 次数 + 1
                                    mStatus = 0; // 拉伸状态清除
                                    if (distance4Calorie >= 1500 && distance4Calorie < 2000) {
                                        calorie = calorie + (mShowWeight / (180 + (Math.random() * 40)));
                                    } else if (distance4Calorie >= 2000 && distance4Calorie < 3000) {
                                        calorie = calorie + (mShowWeight / (130 + (Math.random() * 40)));
                                    } else {
                                        calorie = calorie + (mShowWeight / (80 + (Math.random() * 40)));
                                    }
                                }
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        textShowNumber.setText(String.valueOf(mRealCounts));
                                        textShowCalorie.setText(String.format(Locale.CHINA, "%.1f", calorie));
                                    }
                                });
                                afterAction();
                            }
                        }
                        break;
                    case SerialPortUtils.typeWrite://写
                        byte address01 = ComRecData.bRec[2];
                        byte address02 = ComRecData.bRec[3];
                        if (address01 == SerialPortUtils.addressPower[0] && address02 == SerialPortUtils.addressPower[1] && actionStatus == 0) {//写力量
                            afterAction();
                        }
                        break;
                }
            } else {
                exerciseBuilder.append(TAG).append("校验失败\n");
                builderWExercise(TAG);
            }
        } else {
            if (isEMSwitching) {
                super.onDataReceived(ComRecData);
            }
        }
    }

    private void initTimer() {
        exerciseTimer = new Timer();
        exerciseTask = new TimeCountTask();
    }

    //启动计时器
    private void startTimer() {
        /*
         * java.util.Timer.schedule(TimerTask task, long delay, long period)：
         * 这个方法是说，delay/1000秒后执行task,然后进过period/1000秒再次执行task，
         * 这个用于循环任务，执行无数次，当然，你可以用timer.cancel();取消计时器的执行。
         */
        initTimer();
        try {
            exerciseTimer.schedule(exerciseTask, 1000, 1000);
        } catch (IllegalStateException e) {
            e.printStackTrace();
            initTimer();
            exerciseTimer.schedule(exerciseTask, 1000, 1000);
        }
    }

    private void stopTimer() {
        if (exerciseTimer != null) {
            exerciseTimer.cancel();
        }
        //置零
        exerciseCount = 0;
    }

    private void destroyTimer() {
        exerciseTimer = null;
        exerciseTask = null;
    }

    @Override
    public void onBreakdown(String breakdownType) {
        if (isEMSwitching) return;
        wExercise(breakdownType);
        afterAction();
    }

    private synchronized void afterAction() {
        exerciseBuilder.append(TAG).append("检查是否有后续动作").append("\n");
        builderWExercise(TAG);
        wExercise("检查是否有后续动作");
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                actionStatus = -1;
                switch (otherAfterAction) {
                    case 0:
                        readDistance();
                        break;
                    case 1:
                        otherAfterAction = 0;
                        setPower();
                        break;
                    case 2:
                        otherAfterAction = 0;
                        autoSwitch(true);
                        break;
                    case 3:
                        otherAfterAction = 0;
                        autoSwitch(false);
                        break;
                }
            }
        });
    }


    protected class TimeCountTask extends TimerTask {

        @Override
        public void run() {
            if (isExercise) {
                exerciseCount++;
                if (!isEMSwitching) {
                    afterAction();
                }
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvTargetShowtime.setText(formatTime());
                }
            });
            //2秒无改变重量操作，检查是否需要设置力量*************************************************
            if (isEMSwitching) {
                weightSetCount = 0;
            }
            weightSetCount++;
            if (weightSetCount == 2) {
                weightSetCount = 0;
                if (oldWeight != mShowWeight) {
                    oldWeight = mShowWeight;
                    exerciseBuilder.append(TAG).append("需要发送设置力量命令").append("\n");
                    builderWExercise(TAG);
                    wExercise("需要发送设置力量命令");
                    setPower();
                }
            }
        }
    }

    private String formatTime() {
        int hours, minutes, seconds;
        hours = exerciseCount / 3600;
        minutes = (exerciseCount - hours * 3600) / 60;
        seconds = exerciseCount % 60;
        String timeStr = "";
        if (hours > 0) {
            timeStr = String.format(Locale.CHINA, hours < 10 ? "0%d:" : "%d:", hours);
        }
        timeStr = String.format(Locale.CHINA, minutes < 10 ? "%s0%d:" : "%s%d:", timeStr, minutes);
        timeStr = String.format(Locale.CHINA, seconds < 10 ? "%s0%d" : "%s%d", timeStr, seconds);
        return timeStr;
    }

    @Override
    protected void onPause() {
        super.onPause();
        //当activity不在前台是停止定时
        stopTimer();
    }

    @Override
    public void onDestroy() {
        //销毁时停止定时
        stopTimer();
        destroyTimer();
        isCommandRun = false;
        if (resendThread != null) {
            resendThread.stopSend();
            resendThread = null;
        }
        super.onDestroy();
    }

    protected void wExercise(String message) {
        System.out.println("动作状态：" + actionStatus + "--------------------" + message);
    }

    protected void builderWExercise(String tag) {
//        try {
//            exerciseBuilder.append(String.format(Locale.CHINA, "%s------------------------------------------------------------------------\n", tag));
//            SerialPortUtils.saveLocalDailyLog(exerciseBuilder.toString());
//            exerciseBuilder.delete(0, exerciseBuilder.length());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    @BindView(R.id.img_play_stop)
    ImageView playOrStop;
    @BindView(R.id.play_stop)
    TextView playStopTxt;
    @BindView(R.id.tv_target_showtime)
    TextView tvTargetShowtime;
    @BindView(R.id.tv_target_showweight)
    TextView tvTargetShowWeight;
    @BindView(R.id.text_show_number)
    TextView textShowNumber;
    @BindView(R.id.text_show_calorie)
    TextView textShowCalorie;
}